home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 126-150 / disk_147 / src / buffer.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  15KB  |  584 lines

  1. /*
  2.  *        Buffer handling.
  3.  */
  4. #include    "def.h"
  5. #include    "kbd.h"            /* needed for modes */
  6.  
  7. static RSIZE    itor();
  8.  
  9. /*
  10.  * Attach a buffer to a window. The values of dot and mark come
  11.  * from the buffer if the use count is 0. Otherwise, they come
  12.  * from some other window.  *scratch* is the default alternate
  13.  * buffer.
  14.  */
  15. /*ARGSUSED*/
  16. usebuffer(f, n)
  17. {
  18.     register BUFFER *bp;
  19.     register int    s;
  20.     char        bufn[NBUFN];
  21.  
  22.     /* Get buffer to use from user */
  23.     if ((curbp->b_altb == NULL)
  24.         && ((curbp->b_altb = bfind("*scratch*", TRUE)) == NULL))
  25.         s=eread("Switch to buffer: ", bufn, NBUFN, EFNEW|EFBUF);
  26.     else
  27.         s=eread("Switch to buffer: (default %s) ", bufn, NBUFN,
  28.              EFNEW|EFBUF, curbp->b_altb->b_bname);
  29.  
  30.     if (s == ABORT) return s;
  31.     if (s == FALSE && curbp->b_altb != NULL) bp = curbp->b_altb ;
  32.     else if ((bp=bfind(bufn, TRUE)) == NULL) return FALSE;
  33.  
  34.     /* and put it in current window */
  35.     curbp = bp;
  36.     return showbuffer(bp, curwp, WFFORCE|WFHARD);
  37. }
  38.  
  39. /*
  40.  * pop to buffer asked for by the user.
  41.  */
  42. /*ARGSUSED*/
  43. poptobuffer(f, n)
  44. {
  45.     register BUFFER *bp;
  46.     register WINDOW *wp;
  47.     register int    s;
  48.     char        bufn[NBUFN];
  49.     WINDOW    *popbuf();
  50.  
  51.     /* Get buffer to use from user */
  52.     if ((curbp->b_altb == NULL)
  53.         && ((curbp->b_altb = bfind("*scratch*", TRUE)) == NULL))
  54.         s=eread("Switch to buffer in other window: ", bufn, NBUFN,
  55.             EFNEW|EFBUF);
  56.     else
  57.         s=eread("Switch to buffer in other window: (default %s) ",
  58.              bufn, NBUFN, EFNEW|EFBUF, curbp->b_altb->b_bname);
  59.     if (s == ABORT) return s;
  60.     if (s == FALSE && curbp->b_altb != NULL) bp = curbp->b_altb ;
  61.     else if ((bp=bfind(bufn, TRUE)) == NULL) return FALSE;
  62.  
  63.     /* and put it in a new window */
  64.     if ((wp = popbuf(bp)) == NULL) return FALSE;
  65.     curbp = bp;
  66.     curwp = wp;
  67.     return TRUE;
  68. }
  69.  
  70. /*
  71.  * Dispose of a buffer, by name.
  72.  * Ask for the name. Look it up (don't get too
  73.  * upset if it isn't there at all!). Clear the buffer (ask
  74.  * if the buffer has been changed). Then free the header
  75.  * line and the buffer header. Bound to "C-X K".
  76.  */
  77. /*ARGSUSED*/
  78. killbuffer(f, n)
  79. {
  80.     register BUFFER *bp;
  81.     register BUFFER *bp1;
  82.     register BUFFER *bp2;
  83.     WINDOW        *wp;
  84.     register int    s;
  85.     char        bufn[NBUFN];
  86.  
  87.     if ((s=eread("Kill buffer: (default %s) ", bufn, NBUFN, EFNEW|EFBUF,
  88.             curbp->b_bname)) == ABORT) return (s);
  89.     else if (s == FALSE) bp = curbp;
  90.     else if ((bp=bfind(bufn, FALSE)) == NULL) return FALSE;
  91.  
  92.     /* find some other buffer to display. try the alternate buffer,
  93.      * then the first different buffer in the buffer list.    if
  94.      * there's only one buffer, create buffer *scratch* and make
  95.      * it the alternate buffer.  return if *scratch* is only buffer
  96.      */
  97.     if ((bp1 = bp->b_altb) == NULL) {
  98.         bp1 = (bp == bheadp) ? bp->b_bufp : bheadp;
  99.         if (bp1 == NULL) {
  100.             /* only one buffer. see if it's *scratch* */
  101.             if (bp == bfind("*scratch*",FALSE))
  102.                 return FALSE;
  103.             /* create *scratch* for alternate buffer */
  104.             if ((bp1 = bfind("*scratch*",TRUE)) == NULL)
  105.                 return FALSE;
  106.         }
  107.     }
  108.     if (bclear(bp) != TRUE) return TRUE;
  109.     for (wp = wheadp; bp->b_nwnd > 0; wp = wp->w_wndp) {
  110.         if (wp->w_bufp == bp) {
  111.         bp2 = bp1->b_altb;        /* save alternate buffer */
  112.         if(showbuffer(bp1, wp, WFMODE|WFFORCE|WFHARD) != NULL)
  113.             bp1->b_altb = bp2;
  114.         else    bp1 = bp2;
  115.         }
  116.     }
  117.     if (bp == curbp) curbp = bp1;
  118.     free((char *) bp->b_linep);        /* Release header line. */
  119.     bp2 = NULL;                /* Find the header.    */
  120.     bp1 = bheadp;
  121.     while (bp1 != bp) {
  122.         if (bp1->b_altb == bp)
  123.             bp1->b_altb = (bp->b_altb == bp1) ? NULL : bp->b_altb;
  124.         bp2 = bp1;
  125.         bp1 = bp1->b_bufp;
  126.     }
  127.     bp1 = bp1->b_bufp;            /* Next one in chain.    */
  128.     if (bp2 == NULL)            /* Unlink it.        */
  129.         bheadp = bp1;
  130.     else
  131.         bp2->b_bufp = bp1;
  132.     while (bp1 != NULL) {            /* Finish with altb's    */
  133.         if (bp1->b_altb == bp)
  134.             bp1->b_altb = (bp->b_altb == bp1) ? NULL : bp->b_altb;
  135.         bp1 = bp1->b_bufp;
  136.     }
  137.     free(bp->b_bname);            /* Release name block    */
  138.     free((char *) bp);            /* Release buffer block */
  139.     return TRUE;
  140. }
  141.  
  142. /*
  143.  * Save some buffers - just call anycb with the arg flag.
  144.  */
  145. /*ARGSUSED*/
  146. savebuffers(f, n)
  147. {
  148.     if (anycb(f) == ABORT) return ABORT;
  149.     return TRUE;
  150. }
  151.  
  152. /*
  153.  * Display the buffer list. This is done
  154.  * in two parts. The "makelist" routine figures out
  155.  * the text, and puts it in a buffer. "popbuf"
  156.  * then pops the data onto the screen. Bound to
  157.  * "C-X C-B".
  158.  */
  159. /*ARGSUSED*/
  160. listbuffers(f, n)
  161. {
  162.     register BUFFER *bp;
  163.     register WINDOW *wp;
  164.     BUFFER        *makelist();
  165.     WINDOW        *popbuf();
  166.  
  167.     if ((bp=makelist()) == NULL || (wp=popbuf(bp)) == NULL)
  168.         return FALSE;
  169.     wp->w_dotp = bp->b_dotp;    /* fix up if window already on screen */
  170.     wp->w_doto = bp->b_doto;
  171.     return TRUE;
  172. }
  173.  
  174. /*
  175.  * This routine rebuilds the text for the
  176.  * list buffers command. Return TRUE if
  177.  * everything works. Return FALSE if there
  178.  * is an error (if there is no memory).
  179.  */
  180. BUFFER *
  181. makelist() {
  182.     register char    *cp1;
  183.     register char    *cp2;
  184.     register int    c;
  185.     register BUFFER *bp;
  186.     LINE        *lp;
  187.     register RSIZE    nbytes;
  188.     BUFFER        *blp;
  189.     char        b[6+1];
  190.     char        line[128];
  191.  
  192.     if ((blp = bfind("*Buffer List*", TRUE)) == NULL) return NULL;
  193.     if (bclear(blp) != TRUE) return NULL;
  194.     blp->b_flag &= ~BFCHG;            /* Blow away old.    */
  195.  
  196.     (VOID) strcpy(line, " MR Buffer");
  197.     cp1 = line + 10;
  198.     while(cp1 < line + 4 + NBUFN + 1) *cp1++ = ' ';
  199.     (VOID) strcpy(cp1, "Size   File");
  200.     if (addline(blp, line) == FALSE) return NULL;
  201.     (VOID) strcpy(line, " -- ------");
  202.     cp1 = line + 10;
  203.     while(cp1 < line + 4 + NBUFN + 1) *cp1++ = ' ';
  204.     (VOID) strcpy(cp1, "----   ----");
  205.     if (addline(blp, line) == FALSE) return NULL;
  206.     bp = bheadp;                /* For all buffers    */
  207.     while (bp != NULL) {
  208.         cp1 = &line[0];            /* Start at left edge    */
  209.         *cp1++ = (bp == curbp) ? '.' : ' ';
  210.         *cp1++ = ((bp->b_flag&BFCHG) != 0) ? '*' : ' ';
  211.         *cp1++ = ' ';            /* Gap.            */
  212.         *cp1++ = ' ';
  213.         cp2 = &bp->b_bname[0];        /* Buffer name        */
  214.         while ((c = *cp2++) != 0)
  215.             *cp1++ = c;
  216.         while (cp1 < &line[4+NBUFN+1])
  217.             *cp1++ = ' ';
  218.         nbytes = 0;            /* Count bytes in buf.    */
  219.         if (bp != blp) {
  220.             lp = lforw(bp->b_linep);
  221.             while (lp != bp->b_linep) {
  222.                 nbytes += llength(lp)+1;
  223.                 lp = lforw(lp);
  224.             }
  225.             if(nbytes) nbytes--;    /* no bonus newline    */
  226.         }
  227.         (VOID) itor(b, 6, nbytes);    /* 6 digit buffer size. */
  228.         cp2 = &b[0];
  229.         while ((c = *cp2++) != 0)
  230.             *cp1++ = c;
  231.         *cp1++ = ' ';            /* Gap..            */
  232.         cp2 = &bp->b_fname[0];        /* File name        */
  233.         if (*cp2 != 0) {
  234.             while ((c = *cp2++) != 0) {
  235.                 if (cp1 < &line[128-1])
  236.                     *cp1++ = c;
  237.             }
  238.         }
  239.         *cp1 = 0;            /* Add to the buffer.    */
  240.         if (addline(blp, line) == FALSE)
  241.             return NULL;
  242.         bp = bp->b_bufp;
  243.     }
  244.     blp->b_dotp = lforw(blp->b_linep);    /* put dot at beginning of buffer */
  245.     blp->b_doto = 0;
  246.     return blp;                /* All done        */
  247. }
  248.  
  249. /*
  250.  * Used above.
  251.  */
  252. static RSIZE itor(buf, width, num)
  253. register char buf[]; register int width; register RSIZE num; {
  254.     register RSIZE r;
  255.  
  256.     if (num / 10 == 0) {
  257.         buf[0] = (num % 10) + '0';
  258.         for (r = 1; r < width; buf[r++] = ' ')
  259.             ;
  260.         buf[width] = '\0';
  261.         return 1;
  262.     } else {
  263.         buf[r = itor(buf, width, num / (RSIZE)10)] =
  264.                 (num % (RSIZE)10) + '0';
  265.         return r + 1;
  266.     }
  267.     /*NOTREACHED*/
  268. }
  269.  
  270. /*
  271.  * The argument "text" points to
  272.  * a string. Append this line to the
  273.  * buffer. Handcraft the EOL
  274.  * on the end. Return TRUE if it worked and
  275.  * FALSE if you ran out of room.
  276.  */
  277. addline(bp, text) register BUFFER *bp; char *text; {
  278.     register LINE    *lp;
  279.     register int    i;
  280.     register int    ntext;
  281.  
  282.     ntext = strlen(text);
  283.     if ((lp=lalloc(ntext)) == NULL)
  284.         return FALSE;
  285.     for (i=0; i<ntext; ++i)
  286.         lputc(lp, i, text[i]);
  287.     bp->b_linep->l_bp->l_fp = lp;        /* Hook onto the end    */
  288.     lp->l_bp = bp->b_linep->l_bp;
  289.     bp->b_linep->l_bp = lp;
  290.     lp->l_fp = bp->b_linep;
  291. #ifdef CANTHAPPEN
  292.     if (bp->b_dotp == bp->b_linep)        /* If "." is at the end    */
  293.         bp->b_dotp = lp;        /* move it to new line    */
  294.     if (bp->b_markp == bp->b_linep)        /* ditto for mark    */
  295.         bp->b_markp = lp;
  296. #endif
  297.     return TRUE;
  298. }
  299.  
  300. /*
  301.  * Look through the list of buffers, giving the user
  302.  * a chance to save them.  Return TRUE if there are
  303.  * any changed buffers afterwards. Buffers that don't
  304.  * have an associated file don't count. Return FALSE
  305.  * if there are no changed buffers.
  306.  */
  307. anycb(f) {
  308.     register BUFFER *bp;
  309.     register int    s = FALSE, save = FALSE;
  310.     char        prompt[NFILEN + 11];
  311.     VOID        upmodes();
  312.  
  313.     for (bp = bheadp; bp != NULL; bp = bp->b_bufp) {
  314.         if (*(bp->b_fname) != '\0'
  315.         &&  (bp->b_flag&BFCHG) != 0) {
  316.             (VOID) strcpy(prompt, "Save file ");
  317.             (VOID) strcpy(prompt + 10, bp->b_fname);
  318.             if ((f == TRUE || (save = eyorn(prompt)) == TRUE)
  319.             &&  buffsave(bp) == TRUE) {
  320.                 bp->b_flag &= ~BFCHG;
  321.                 upmodes(bp);
  322.             } else s = TRUE;
  323.             if (save == ABORT) return (save);
  324.             save = TRUE;
  325.         }
  326.     }
  327.     if (save == FALSE /* && kbdmop == NULL */ )    /* experimental */
  328.         ewprintf("(No files need saving)");
  329.     return s;
  330. }
  331.  
  332. /*
  333.  * Search for a buffer, by name.
  334.  * If not found, and the "cflag" is TRUE,
  335.  * create a buffer and put it in the list of
  336.  * all buffers. Return pointer to the BUFFER
  337.  * block for the buffer.
  338.  */
  339. BUFFER    *
  340. bfind(bname, cflag) register char *bname; {
  341.     register BUFFER *bp;
  342.     char        *malloc();
  343.     register LINE    *lp;
  344.     int i;
  345.     extern int defb_nmodes;
  346.     extern MAPS *defb_modes[PBMODES];
  347.     extern int defb_flag;
  348.  
  349.     bp = bheadp;
  350.     while (bp != NULL) {
  351.         if (fncmp(bname, bp->b_bname) == 0)
  352.             return bp;
  353.         bp = bp->b_bufp;
  354.     }
  355.     if (cflag!=TRUE) return NULL;
  356.     /*NOSTRICT*/
  357.     if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL) {
  358.         ewprintf("Can't get %d bytes", sizeof(BUFFER));
  359.         return NULL;
  360.     }
  361.     if ((bp->b_bname=malloc((unsigned)(strlen(bname)+1))) == NULL) {
  362.         ewprintf("Can't get %d bytes", strlen(bname)+1);
  363.         free((char *) bp);
  364.         return NULL;
  365.     }
  366.     if ((lp = lalloc(0)) == NULL) {
  367.         free(bp->b_bname);
  368.         free((char *) bp);
  369.         return NULL;
  370.     }
  371.     bp->b_altb = bp->b_bufp     = NULL;
  372.     bp->b_dotp  = lp;
  373.     bp->b_doto  = 0;
  374.     bp->b_markp = NULL;
  375.     bp->b_marko = 0;
  376.     bp->b_flag  = defb_flag;
  377.     bp->b_nwnd  = 0;
  378.     bp->b_linep = lp;
  379.     bp->b_nmodes = defb_nmodes;
  380.     i = 0;
  381.     do {
  382.         bp->b_modes[i] = defb_modes[i];
  383.     } while(i++ < defb_nmodes);
  384.     bp->b_fname[0] = '\0';
  385.     (VOID) strcpy(bp->b_bname, bname);
  386.     lp->l_fp = lp;
  387.     lp->l_bp = lp;
  388.     bp->b_bufp = bheadp;
  389.     bheadp = bp;
  390.     return bp;
  391. }
  392.  
  393. /*
  394.  * This routine blows away all of the text
  395.  * in a buffer. If the buffer is marked as changed
  396.  * then we ask if it is ok to blow it away; this is
  397.  * to save the user the grief of losing text. The
  398.  * window chain is nearly always wrong if this gets
  399.  * called; the caller must arrange for the updates
  400.  * that are required. Return TRUE if everything
  401.  * looks good.
  402.  */
  403. bclear(bp) register BUFFER *bp; {
  404.     register LINE    *lp;
  405.     register int    s;
  406.     VOID        lfree();
  407.  
  408.     if ((bp->b_flag&BFCHG) != 0        /* Changed.        */
  409.     && (s=eyesno("Buffer modified; kill anyway")) != TRUE)
  410.         return (s);
  411.     bp->b_flag  &= ~BFCHG;            /* Not changed        */
  412.     while ((lp=lforw(bp->b_linep)) != bp->b_linep)
  413.         lfree(lp);
  414.     bp->b_dotp  = bp->b_linep;        /* Fix "."        */
  415.     bp->b_doto  = 0;
  416.     bp->b_markp = NULL;            /* Invalidate "mark"    */
  417.     bp->b_marko = 0;
  418.     return TRUE;
  419. }
  420.  
  421. /*
  422.  * Display the given buffer in the given window. Flags indicated
  423.  * action on redisplay.
  424.  */
  425. showbuffer(bp, wp, flags) register BUFFER *bp; register WINDOW *wp; {
  426.     register BUFFER *obp;
  427.     WINDOW        *owp;
  428.  
  429.     if (wp->w_bufp == bp) {            /* Easy case!    */
  430.         wp->w_flag |= flags;
  431.         return TRUE;
  432.     }
  433.  
  434.     /* First, dettach the old buffer from the window */
  435.     if ((bp->b_altb = obp = wp->w_bufp) != NULL) {
  436.         if (--obp->b_nwnd == 0) {
  437.             obp->b_dotp  = wp->w_dotp;
  438.             obp->b_doto  = wp->w_doto;
  439.             obp->b_markp = wp->w_markp;
  440.             obp->b_marko = wp->w_marko;
  441.         }
  442.     }
  443.  
  444.     /* Now, attach the new buffer to the window */
  445.     wp->w_bufp = bp;
  446.  
  447.     if (bp->b_nwnd++ == 0) {        /* First use.        */
  448.         wp->w_dotp  = bp->b_dotp;
  449.         wp->w_doto  = bp->b_doto;
  450.         wp->w_markp = bp->b_markp;
  451.         wp->w_marko = bp->b_marko;
  452.     } else
  453.     /* already on screen, steal values from other window */
  454.         for (owp = wheadp; owp != NULL; owp = wp->w_wndp)
  455.             if (wp->w_bufp == bp && owp != wp) {
  456.                 wp->w_dotp  = owp->w_dotp;
  457.                 wp->w_doto  = owp->w_doto;
  458.                 wp->w_markp = owp->w_markp;
  459.                 wp->w_marko = owp->w_marko;
  460.                 break;
  461.             }
  462.     wp->w_flag |= WFMODE|flags;
  463.     return TRUE;
  464. }
  465.  
  466. /*
  467.  * Pop the buffer we got passed onto the screen.
  468.  * Returns a status.
  469.  */
  470. WINDOW *
  471. popbuf(bp) register BUFFER *bp; {
  472.     register WINDOW *wp;
  473.  
  474.     if (bp->b_nwnd == 0) {        /* Not on screen yet.    */
  475.         if ((wp=wpopup()) == NULL) return NULL;
  476.     } else
  477.         for (wp = wheadp; wp != NULL; wp = wp->w_wndp)
  478.             if (wp->w_bufp == bp) {
  479.                 wp->w_flag |= WFHARD|WFFORCE;
  480.                 return wp ;
  481.             }
  482.     if (showbuffer(bp, wp, WFHARD) != TRUE) return NULL;
  483.     return wp;
  484. }
  485.  
  486. /*
  487.  * Insert another buffer at dot.  Very useful.
  488.  */
  489. /*ARGSUSED*/
  490. bufferinsert(f, n)
  491. {
  492.     register BUFFER *bp;
  493.     register LINE    *clp;
  494.     register int    clo;
  495.     register int    nline;
  496.     int        s;
  497.     char        bufn[NBUFN];
  498.  
  499.     /* Get buffer to use from user */
  500.     if (curbp->b_altb != NULL)
  501.         s=eread("Insert buffer: (default %s) ", bufn, NBUFN,
  502.              EFNEW|EFBUF, &(curbp->b_altb->b_bname),
  503.              (char *) NULL) ;
  504.     else
  505.         s=eread("Insert buffer: ", bufn, NBUFN, EFNEW|EFBUF,
  506.              (char *) NULL) ;
  507.     if (s == ABORT) return (s);
  508.     if (s == FALSE && curbp->b_altb != NULL) bp = curbp->b_altb;
  509.     else if ((bp=bfind(bufn, FALSE)) == NULL) return FALSE;
  510.  
  511.     if (bp==curbp) {
  512.         ewprintf("Cannot insert buffer into self");
  513.         return FALSE;
  514.     }
  515.  
  516.     /* insert the buffer */
  517.     nline = 0;
  518.     clp = lforw(bp->b_linep);
  519.     for(;;) {
  520.         for (clo = 0; clo < llength(clp); clo++)
  521.             if (linsert(1, lgetc(clp, clo)) == FALSE)
  522.                 return FALSE;
  523.         if((clp = lforw(clp)) == bp->b_linep) break;
  524.         if (newline(FFRAND, 1) == FALSE) /* fake newline */
  525.             return FALSE;
  526.         nline++;
  527.     }
  528.     if (nline == 1) ewprintf("[Inserted 1 line]");
  529.     else    ewprintf("[Inserted %d lines]", nline);
  530.  
  531.     clp = curwp->w_linep;            /* cosmetic adjustment */
  532.     if (curwp->w_dotp == clp) {        /* for offscreen insert */
  533.         while (nline-- && lback(clp)!=curbp->b_linep)
  534.             clp = lback(clp);
  535.         curwp->w_linep = clp;        /* adjust framing.    */
  536.         curwp->w_flag |= WFHARD;
  537.     }
  538.     return (TRUE);
  539. }
  540.  
  541. /*
  542.  * Turn off the dirty bit on this buffer.
  543.  */
  544. /*ARGSUSED*/
  545. notmodified(f, n)
  546. {
  547.     register WINDOW *wp;
  548.  
  549.     curbp->b_flag &= ~BFCHG;
  550.     wp = wheadp;                /* Update mode lines.    */
  551.     while (wp != NULL) {
  552.         if (wp->w_bufp == curbp)
  553.             wp->w_flag |= WFMODE;
  554.         wp = wp->w_wndp;
  555.     }
  556.     ewprintf("Modification-flag cleared");
  557.     return TRUE;
  558. }
  559.  
  560. #ifndef NO_HELP
  561. /*
  562.  * Popbuf and set all windows to top of buffer.     Currently only used by
  563.  * help functions.
  564.  */
  565.  
  566. popbuftop(bp)
  567. register BUFFER *bp;
  568. {
  569.     register WINDOW *wp;
  570.  
  571.     bp->b_dotp = lforw(bp->b_linep);
  572.     bp->b_doto = 0;
  573.     if(bp->b_nwnd != 0) {
  574.     for(wp = wheadp; wp!=NULL; wp = wp->w_wndp)
  575.         if(wp->w_bufp == bp) {
  576.         wp->w_dotp = bp->b_dotp;
  577.         wp->w_doto = 0;
  578.         wp->w_flag |= WFHARD;
  579.         }
  580.     }
  581.     return popbuf(bp) != NULL;
  582. }
  583. #endif
  584.